/*
*********************************************************************************************************
*                                             uC/GUI V3.98
*                        Universal graphic software for embedded applications
*
*                       (c) Copyright 2002, Micrium Inc., Weston, FL
*                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
*              �C/GUI is protected by international copyright laws. Knowledge of the
*              source code may not be used to write a similar product. This file may
*              only be used in accordance with a license and should not be redistributed
*              in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File        : GUICirc.C
Purpose     : Circle and ellipse drawing functions
----------------------------------------------------------------------
Version-Date---Author-Explanation
----------------------------------------------------------------------
1.00.02 011115 JE     a) GL_FillEllipse, GL_FillCircle, GL_DrawCircle changed
1.00.01 011113 JE     a) GL_DrawEllipse changed
1.00.00 991206 RS     First release
----------------------------------------------------------------------
Known problems or limitations with current version
----------------------------------------------------------------------
None.
----------------------------------------------------------------------
Open issues
----------------------------------------------------------------------
None
---------------------------END-OF-HEADER------------------------------
*/

//#include <stddef.h>           /* needed for definition of NULL */
#include "GUI_Private.h"

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       Draw8Point
*/
static void Draw8Point(I32 x0,I32 y0, I32 xoff, I32 yoff)
{
	LCD_HL_DrawPixel(x0+xoff,y0+yoff);
	LCD_HL_DrawPixel(x0-xoff,y0+yoff);
	LCD_HL_DrawPixel(x0+yoff,y0+xoff);
	LCD_HL_DrawPixel(x0+yoff,y0-xoff);
	if (yoff) {
		LCD_HL_DrawPixel(x0+xoff,y0-yoff);
		LCD_HL_DrawPixel(x0-xoff,y0-yoff);
		LCD_HL_DrawPixel(x0-yoff,y0+xoff);
		LCD_HL_DrawPixel(x0-yoff,y0-xoff);
	}
}

/*********************************************************************
*
*       Public code, circle
*
**********************************************************************
*/
/*********************************************************************
*
*       GL_DrawCircle
*/
void GL_DrawCircle(I32 x0, I32 y0, I32 r)
{
	I32 i;
	I32 imax = ((I32)((I32)r*707))/1000+1;
	I32 sqmax = (I32)r*(I32)r+(I32)r/2;
	I32 y=r;
	Draw8Point(x0,y0,r,0);
	for (i=1; i<= imax; i++) {
		if ((i*i+y*y) >sqmax) {
			Draw8Point(x0,y0,i,y);
			y--;
		}
		Draw8Point(x0,y0,i,y);
	}
}

/*********************************************************************
*
*       GUI_DrawCircle
*/
void GUI_DrawCircle(I32 x0, I32 y0, I32 r)
{
	GL_DrawCircle( x0, y0, r);
}

/*********************************************************************
*
*       GL_FillCircle
*/
void GL_FillCircle(I32 x0, I32 y0, I32 r)
{
	I32 i;
	I32 imax = ((I32)((I32)r*707))/1000+1;
	I32 sqmax = (I32)r*(I32)r+(I32)r/2;
	I32 x=r;
	LCD_HL_DrawHLine(x0-r,y0,x0+r);
	for (i=1; i<= imax; i++) {
		if ((i*i+x*x) >sqmax) {
			/* draw lines from outside */
			if (x>imax) {
				LCD_HL_DrawHLine (x0-i+1,y0+x, x0+i-1);
				LCD_HL_DrawHLine (x0-i+1,y0-x, x0+i-1);
			}
			x--;
		}
		/* draw lines from inside (center) */
		LCD_HL_DrawHLine(x0-x,y0+i, x0+x);
		LCD_HL_DrawHLine(x0-x,y0-i, x0+x);
	}
}

/*********************************************************************
*
*       GUI_FillCircle
*/
void GUI_FillCircle(I32 x0, I32 y0, I32 r)
{
#if (GUI_WINSUPPORT)
    WM_ADDORG(x0,y0);
#endif
  GL_FillCircle(x0,y0,r);
}

/*********************************************************************
*
*       Public code, ellipse
*
* The most efficient way to calculate the ellipse positions is using
* the knowledge that the ellipse is just circle which has compressed
* (or stretched) in one direction. For a circle, the following
* equation holds true for all points located on the border of it:
*
*               x^2 + y(x)^2 = r^2 = const
*
* Therefor, for an ellipse we can make use of the following equation:
*
*               (ry*x)^2 + (rx*y(x))^2 = (ry*rx)^2 = const
*
**********************************************************************
*/
/*********************************************************************
*
*       GL_FillEllipse
*/
void GL_FillEllipse(I32 x0, I32 y0, I32 rx, I32 ry)
{
	I32 OutConst, Sum, SumY;
	I32 x,y;
	U32 _rx = rx;
	U32 _ry = ry;
	OutConst = _rx*_rx*_ry*_ry  /* Constant as explaint above */
			+(_rx*_rx*_ry>>1); /* To compensate for rounding */
	x = rx;
	for (y=0; y<=ry; y++) {
		SumY =((I32)(rx*rx))*((I32)(y*y)); /* Does not change in loop */
		while (Sum = SumY + ((I32)(ry*ry))*((I32)(x*x)),
				(x>0) && (Sum>OutConst)){
			x--;
		}
		LCD_HL_DrawHLine(x0-x, y0+y, x0+x);
		if (y)
			LCD_HL_DrawHLine(x0-x, y0-y, x0+x);
	}
}

/*********************************************************************
*
*       GUI_FillEllipse
*/
void GUI_FillEllipse(I32 x0, I32 y0, I32 rx, I32 ry)
{
	GL_FillEllipse (x0,y0, rx, ry);
}

/*********************************************************************
*
*       GL_DrawEllipse
*/
void GL_DrawEllipse(I32 x0, I32 y0, I32 rx, I32 ry)
{
	I32 OutConst, Sum, SumY;
	I32 x,y;
	I32 xOld;
	U32 _rx = rx;
	U32 _ry = ry;
	OutConst = _rx*_rx*_ry*_ry  /* Constant as explaint above */
			+(_rx*_rx*_ry>>1); /* To compensate for rounding */
	xOld = x = rx;
	for (y=0; y<=ry; y++) {
		if (y==ry) {
			x=0;
		} else {
			SumY =((I32)(rx*rx))*((I32)(y*y)); /* Does not change in loop */
			while (Sum = SumY + ((I32)(ry*ry))*((I32)(x*x)),
					(x>0) && (Sum>OutConst)) x--;
		}
		/* Since we draw lines, we can not draw on the first
		iteration
		*/
		if (y) {
			GL_DrawLine1(x0-xOld,y0-y+1,x0-x,y0-y);
			GL_DrawLine1(x0-xOld,y0+y-1,x0-x,y0+y);
			GL_DrawLine1(x0+xOld,y0-y+1,x0+x,y0-y);
			GL_DrawLine1(x0+xOld,y0+y-1,x0+x,y0+y);
		}
		xOld = x;
	}
}

/*********************************************************************
*
*       GUI_DrawEllipse
*/
void GUI_DrawEllipse(I32 x0, I32 y0, I32 rx, I32 ry)
{
	GL_DrawEllipse(x0, y0, rx, ry);
}

/*************************** End of file ****************************/
	 	 			 		    	 				 	  			   	 	 	 	 	 	  	  	      	   		 	 	 		  		  	 		 	  	  			     			       	   	 			  		    	 	     	 				  	 					 	 			   	  	  			 				 		 	 	 			     			 
